﻿using UnityEngine;
using System.Collections;
using System;
using UnityEditor;
using System.IO;
using System.Xml;

public static class MakeTPFont
{

    [MenuItem("Assets/Make TexturePackage Font", true)]
    static public bool ValidateMakeFont()
    {
        // 选中png贴图或者fnt
        if (Selection.activeObject == null) return false;
        return Selection.activeObject is Texture2D && AssetDatabase.GetAssetPath(Selection.activeObject).EndsWith(".png")
            || Selection.activeObject is TextAsset && AssetDatabase.GetAssetPath(Selection.activeObject).EndsWith(".fnt");
    }
    [MenuItem("Assets/Make TexturePackage Font")]
    public static void MakeFont()
    {
        var path = AssetDatabase.GetAssetPath(Selection.activeObject);
        path = path.Split('.')[0] + ".fnt";
        Debug.LogWarning(path);
        var fnt = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)) as TextAsset;
        if (fnt == null)
        {
            throw new UnityException(Selection.activeObject.name + " TextAsset doesn't exist for " + path);
        }
        path = path.Split('.')[0] + ".png";
        Debug.LogWarning(path);
        var texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
        if (texture == null)
        {
            throw new UnityException(Selection.activeObject.name + " Texture2d doesn't exist for " + path);
        }
        MakeFont(fnt, texture);
    }

    private static void MakeFont(TextAsset fnt, Texture2D texture)
    {
        var path = AssetDatabase.GetAssetPath(fnt);
        XmlDocument xml = new XmlDocument();
        xml.LoadXml(fnt.text);
        XmlNodeList chars = xml.GetElementsByTagName("chars")[0].ChildNodes;
        float texW = texture.width;
        float texH = texture.height;
        CharacterInfo[] charInfos = new CharacterInfo[chars.Count + 1];
        Rect r;
        Vector2 sizeHeight = new Vector2();
        for (int i = 0; i < chars.Count; i++)
        {
            XmlNode charNode = chars[i];
            if (charNode.Attributes != null)
            {
                CharacterInfo charInfo = new CharacterInfo();
                var node = new ChaInfo(charNode);
                charInfo.index = node.index;
                charInfo.advance = node.width;
                if (node.width > sizeHeight.x)
                {
                    sizeHeight.x = node.width;
                }
                if (node.height > sizeHeight.y)
                {
                    sizeHeight.y = node.height;
                }
                r = new Rect();
                r.x = (float)node.x / texW;
                r.y = (float)node.y / texH;
                r.width = (float)node.width / texW;
                r.height = (float)node.height / texH;
                r.y = 1f - r.y - r.height;
                charInfo.uvBottomLeft = new Vector2(r.xMin, r.yMin);
                charInfo.uvBottomRight = new Vector2(r.xMax, r.yMin);
                charInfo.uvTopLeft = new Vector2(r.xMin, r.yMax);
                charInfo.uvTopRight = new Vector2(r.xMax, r.yMax);

                r = new Rect();
                r.x = 0;
                r.y = 0;
                r.width = (float)ToFloat(charNode, "width");
                r.height = (float)ToFloat(charNode, "height");
                r.y = -r.y;
                r.height = -r.height;
                charInfo.minX = (int)r.xMin;
                charInfo.maxX = (int)r.xMax;
                charInfo.minY = (int)r.yMax;
                charInfo.maxY = (int)r.yMin;

                charInfos[i] = charInfo;
            }
        }
        var blankSpace = new CharacterInfo();
        blankSpace.index = 32;
        blankSpace.advance = (int)sizeHeight.x;
        blankSpace.uvBottomLeft = blankSpace.uvBottomRight = blankSpace.uvTopLeft = blankSpace.uvTopRight = Vector2.zero;
        blankSpace.minX = blankSpace.maxX = blankSpace.minY = blankSpace.maxY = 0;
        charInfos[chars.Count] = blankSpace;


        path = path.Replace(".fnt", ".mat");
        var shader = Shader.Find("UI/Default");
        Material material = AssetDatabase.LoadAssetAtPath(path, typeof(Material)) as Material;
        if (material == null || true)
        {
            material = new Material(shader);
            AssetDatabase.CreateAsset(material, path);
        }
        if (material.shader != shader)
        {
            material.shader = shader;
        }
        material.mainTexture = texture;
        path = path.Replace(".mat", ".fontsettings");
        var font = AssetDatabase.LoadAssetAtPath(path, typeof(Font)) as Font;
        if (font == null || true)
        {
            font = new Font();
            AssetDatabase.CreateAsset(font, path);
        }
        font.material = material;
        font.name = fnt.name;
        font.characterInfo = charInfos;
        SerializedObject mFont = new SerializedObject(font);
        // 设置字体大小
        mFont.FindProperty("m_FontSize").floatValue = sizeHeight.x;
        // 设置换行
        mFont.FindProperty("m_LineSpacing").floatValue = sizeHeight.y;
        mFont.ApplyModifiedProperties();
        AssetDatabase.Refresh();
    }

    public class ChaInfo
    {
        public ChaInfo(XmlNode node)
        {
            index = int.Parse(node.Attributes.GetNamedItem("id").InnerText);
            x = int.Parse(node.Attributes.GetNamedItem("x").InnerText);
            y = int.Parse(node.Attributes.GetNamedItem("y").InnerText);
            width = int.Parse(node.Attributes.GetNamedItem("width").InnerText);
            height = int.Parse(node.Attributes.GetNamedItem("height").InnerText);
        }
        public int index;
        public int x;
        public int y;
        public int width;
        public int height;

    }
    private static float ToFloat(XmlNode node, string name)
    {
        return float.Parse(node.Attributes.GetNamedItem(name).InnerText);
    }
}
